'use strict';
const Generators = require('yeoman-generator');
const utils = require('../../utils/all');
const prompts = require('./prompts');
const path = require('path');
const fs = require('fs');
const packageInfo = require('../../package.json');

// Set the base root directory for our files. Make sure to always use the node_modules
// base path instead of the require call only. This is needed because require.resolve
// also includes the path set in package.json main keys!
const baseRootPath = path.join(path.dirname(require.resolve('react-webpack-template')), '..');

/**
 * Base generator. Will copy all required files from react-webpack-template
 */
class AppGenerator extends Generators.Base {

  constructor(args, options) {

    super(args, options);

    // Make options available
    this.option('skip-welcome-message', {
      desc: 'Skip the welcome message',
      type: Boolean,
      defaults: false
    });
    this.option('skip-install');

    // Use our plain template as source
    this.sourceRoot(baseRootPath);

    this.config.save();
  }

  initializing() {

    if(!this.options['skip-welcome-message']) {
      this.log(require('yeoman-welcome'));
      this.log('Out of the box I include Webpack and some default React components.\n');
    }
  }

  prompting() {

    return this.prompt(prompts).then((answers) => {

      // Make sure to get the correct app name if it is not the default
      if(answers.appName !== utils.yeoman.getAppName()) {
        answers.appName = utils.yeoman.getAppName(answers.appName);
      }

      // Set needed global vars for yo
      this.appName = answers.appName;
      this.style = answers.style;
      this.cssmodules = answers.cssmodules;
      this.postcss = answers.postcss;
      this.generatedWithVersion = parseInt(packageInfo.version.split('.').shift(), 10);

      // Set needed keys into config
      this.config.set('appName', this.appName);
      this.config.set('appPath', this.appPath);
      this.config.set('style', this.style);
      this.config.set('cssmodules', this.cssmodules);
      this.config.set('postcss', this.postcss);
      this.config.set('generatedWithVersion', this.generatedWithVersion);
    });
  }

  configuring() {

    // Generate our package.json. Make sure to also include the required dependencies for styles
    let defaultSettings = this.fs.readJSON(`${baseRootPath}/package.json`);
    let packageSettings = {
      name: this.appName,
      private: true,
      version: '0.0.1',
      description: `${this.appName} - Generated by generator-react-webpack`,
      main: 'src/index.js',
      scripts: defaultSettings.scripts,
      repository: '',
      keywords: [],
      author: 'Your name here',
      devDependencies: defaultSettings.devDependencies,
      dependencies: defaultSettings.dependencies
    };

    // Add needed loaders if we have special styles
    let styleConfig = utils.config.getChoiceByKey('style', this.style);
    if(styleConfig && styleConfig.packages) {

      for(let dependency of styleConfig.packages) {
        packageSettings.devDependencies[dependency.name] = dependency.version;
      }
    }

    // Add postcss module if enabled
    let postcssConfig = utils.config.getChoiceByKey('postcss', 'postcss');
    if(this.postcss && postcssConfig && postcssConfig.packages) {

      for(let dependency of postcssConfig.packages) {
        packageSettings.devDependencies[dependency.name] = dependency.version;
      }
    }

    // Add cssmodules if enabled
    const cssmoduleConfig = utils.config.getChoiceByKey('cssmodules', 'cssmodules');
    if(this.cssmodules && cssmoduleConfig && cssmoduleConfig.packages) {
      for(let dependency of cssmoduleConfig.packages) {
        packageSettings.dependencies[dependency.name] = dependency.version;
      }
    }

    this.fs.writeJSON(this.destinationPath('package.json'), packageSettings);
  }

  writing() {

    const excludeList = [
      'LICENSE',
      'README.md',
      'CHANGELOG.md',
      'node_modules',
      'package.json',
      '.istanbul.yml',
      '.travis.yml'
    ];

    // Get all files in our repo and copy the ones we should
    fs.readdir(this.sourceRoot(), (err, items) => {

      for(let item of items) {

        // Skip the item if it is in our exclude list
        if(excludeList.indexOf(item) !== -1) {
          continue;
        }

        // Copy all items to our root
        let fullPath = path.join(baseRootPath, item);
        if(fs.lstatSync(fullPath).isDirectory()) {
          this.bulkDirectory(item, item);
        } else {
          if (item === '.npmignore') {
            this.copy(item, '.gitignore');
          } else {
            this.copy(item, item);
          }
        }
      }
    });
  }

  install() {

    // Currently buggy!
    if(this.postcss) {
      const postcss = require('./postcss');
      postcss.write(path.join(this.destinationRoot(), 'conf/webpack/Base.js'));
    }

    if(!this.options['skip-install']) {
      this.installDependencies({ bower: false });
    }
  }
}

module.exports = AppGenerator;
